/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "led.h"
#include "buzzer.h"
#include "seg7.h"
#include "key.h"
#include "uart_comm.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/**
 * @brief 硬件初始状态测试函数
 * @param None
 * @retval None
 */
static void Hardware_Test_Init(void) {
    // LED状态测试 - 验证LED控制功能
    LED1_ON();    // 点亮LED1
    LED2_OFF();   // 熄灭LED2
    LED3_ON();    // 点亮LED3
    LED4_OFF();   // 熄灭LED4
    
    // 数码管初始测试 - 验证段码表正确性
    SEG7_DisplayDigitNew(8);  // 显示数字8
    
    // 延时观察初始状态
    HAL_Delay(2000);
}

/**
 * @brief 数码管循环显示任务
 * @param current_digit: 当前显示的数字指针
 * @param last_switch_time: 上次切换时间指针
 * @retval None
 */
static void SEG7_Display_Task(void) {
    static uint8_t current_digit = 0;      // 静态变量保存当前显示数字
    static uint32_t last_switch_time = 0;  // 静态变量保存上次切换时间
    uint32_t current_time = HAL_GetTick();
    
    // 数码管数字循环显示（每100ms切换一次）
    if (current_time - last_switch_time >= 500) {
        SEG7_DisplayDigitNew(current_digit);
        current_digit = (current_digit + 1) % 10;
        last_switch_time = current_time;
        if(current_digit==0)
        {
            BUZZER_ON();
        }
        else
        {
            BUZZER_OFF();
        }
    }
}

/**
 * @brief TM1650四位数码管循环显示任务
 * @retval None
 */
static void TM1650_Display_Task(void) {
    static uint16_t current_number = 0;    // 静态变量保存当前显示数字
    static uint32_t last_switch_time = 0;  // 静态变量保存上次切换时间
    uint32_t current_time = HAL_GetTick();
    
    // TM1650数字循环显示（每1秒切换一次）
    if (current_time - last_switch_time >= 100) {
        TM1650_WriteNumber(current_number);
        current_number = (current_number + 1) % 10000;  // 0-9999循环
        last_switch_time = current_time;
    }
}

/**
 * @brief ADC测试任务 - 定期读取ADC值并通过UART输出
 * @param None
 * @retval None
 */
static void ADC_Test_Task(void) {
    static uint32_t last_adc_time = 0;
    static uint16_t adc_counter = 0;
    uint32_t current_time = HAL_GetTick();

    char adc_info[128];
    
    // 每1秒读取一次ADC值
    if (current_time - last_adc_time >= 500) {
        last_adc_time = current_time;
        adc_counter++;
        
        // 定义要读取的通道
        uint16_t channels[] = {0, 1};  // 读取通道0和通道1
        uint8_t channel_count = 2;
        channels[0]=ADC_Read_Channel(0);
				 
        // 通过协议发送ADC数据
       // ADC_Send_Protocol_Data(channels, channel_count);
        
        // // 同时通过UART发送调试信息（可选）
				sprintf(adc_info, "ADC Reading channel 0 %d:\r\n", 
                  channels[0]);
         UART_SendString(adc_info);
         UART_SendString("----------------------------------------\r\n");
    }
}

// LED转圈圈效果 - 始终保持3个连续的LED亮
void led_circle_task(void) {
    static uint8_t led_state = 0;        // LED状态 (0-3)
    static uint8_t circle_count = 0;     // 转圈计数
    static uint32_t last_tick = 0;       // 上次更新时间
    static uint8_t buzzer_on = 0;        // 蜂鸣器状态
    static uint32_t buzzer_tick = 0;     // 蜂鸣器计时
    
    uint32_t now = HAL_GetTick();
    
    // 蜂鸣器控制
    if (buzzer_on) {
        if (now - buzzer_tick >= 200) {  // 响500ms后关闭
            BUZZER_OFF();
            buzzer_on = 0;
            circle_count = 0;  // 重置计数
        }
        return;  // 蜂鸣器响时暂停LED变化
    }
    
    // LED转圈逻辑 - 每150ms切换一次
    if (now - last_tick >= 100) {
        last_tick = now;
        
        // 关闭所有LED
        LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_OFF();
        
        // 点亮3个连续的LED
        switch (led_state) {
            case 0:  // LED4,3,2亮
                LED4_ON(); LED3_ON(); LED2_ON();
                break;
            case 1:  // LED3,2,1亮
                LED3_ON(); LED2_ON(); LED1_ON();
                break;
            case 2:  // LED2,1,4亮
                LED2_ON(); LED1_ON(); LED4_ON();
                break;
            case 3:  // LED1,4,3亮
                LED1_ON(); LED4_ON(); LED3_ON();
                circle_count++;  // 完成一圈
                break;
        }
        
        led_state = (led_state + 1) % 4;
        
        // 转完10圈后开启蜂鸣器
        if (circle_count >= 10) {
            BUZZER_ON();
            buzzer_on = 1;
            buzzer_tick = now;
        }
    }
}

// 原有的LED和蜂鸣器控制任务（保持不变）
void led_buzzer_task(void) {
    static uint8_t led_state = 0;
    static uint32_t last_tick = 0;
    uint32_t now = HAL_GetTick();
    if (now - last_tick >= 100) {
        last_tick = now;
        switch (led_state) {
            case 0:
                LED1_ON(); LED2_OFF(); LED3_OFF(); LED4_OFF();
                BUZZER_OFF();
                break;
            case 1:
                LED1_OFF(); LED2_ON(); LED3_OFF(); LED4_OFF();
                BUZZER_OFF();
                break;
            case 2:
                LED1_OFF(); LED2_OFF(); LED3_ON(); LED4_OFF();
                BUZZER_OFF();
                break;
            case 3:
                LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_ON();
                BUZZER_ON();
                break;
        }
        led_state = (led_state + 1) % 4;
    }
}

/**
 * @brief 串口通信演示任务
 * @param None
 * @retval None
 */
static void UART_Comm_Demo_Task(void) {
    static uint32_t last_send_time = 0;
    static uint8_t demo_counter = 0;
    char rx_buffer[128];
    char tx_buffer[128];
    UART_RX_Status_t rx_status;
    
    uint32_t current_time = HAL_GetTick();
    
    // 每5秒发送一次演示数据
    if (current_time - last_send_time >= 5000) {
        last_send_time = current_time;
        demo_counter++;
        
        // 发送演示字符串
        sprintf(tx_buffer, "Hello from STM32! Counter: %d\r\n", demo_counter);
        UART_SendString(tx_buffer);
        
        // 发送当前系统时间
        sprintf(tx_buffer, "System Time: %lu ms\r\n", current_time);
        UART_SendString(tx_buffer);
        
        // 发送LED状态信息
        sprintf(tx_buffer, "LED Status: Demo Counter = %d\r\n", demo_counter);
        UART_SendString(tx_buffer);
    }
    
    // 检查是否有接收到的数据
    if (UART_GetRxDataLength() > 0) {
        // 尝试接收一行数据
        rx_status = UART_ReceiveLine(rx_buffer, sizeof(rx_buffer), 100);
        
        if (rx_status == UART_RX_OK) {
            // 回显接收到的数据
            sprintf(tx_buffer, "Received: %s\r\n", rx_buffer);
            UART_SendString(tx_buffer);
            
            // 根据接收到的命令执行相应操作
            if (strstr(rx_buffer, "LED_ON") != NULL) {
                LED1_ON();
                UART_SendString("LED1 turned ON\r\n");
            }
            else if (strstr(rx_buffer, "LED_OFF") != NULL) {
                LED1_OFF();
                UART_SendString("LED1 turned OFF\r\n");
            }
            else if (strstr(rx_buffer, "BUZZER_ON") != NULL) {
                BUZZER_ON();
                UART_SendString("Buzzer turned ON\r\n");
            }
            else if (strstr(rx_buffer, "BUZZER_OFF") != NULL) {
                BUZZER_OFF();
                UART_SendString("Buzzer turned OFF\r\n");
            }
            else if (strstr(rx_buffer, "HELP") != NULL) {
                UART_SendString("Available commands:\r\n");
                UART_SendString("  LED_ON - Turn on LED1\r\n");
                UART_SendString("  LED_OFF - Turn off LED1\r\n");
                UART_SendString("  BUZZER_ON - Turn on buzzer\r\n");
                UART_SendString("  BUZZER_OFF - Turn off buzzer\r\n");
                UART_SendString("  HELP - Show this help\r\n");
            }
        }
    }
}

/**
 * @brief 开机信息显示函数
 * @param None
 * @retval None
 * @note   结合LED、数码管、蜂鸣器和串口展示开机信息
 */
static void System_Boot_Info_Display(void) {
    // 变量定义 - 放在函数开头以提高编译器兼容性
    uint8_t i;
    uint32_t start_time;
    char boot_info[128];
    
    // ==================== 第一阶段：系统启动提示 ====================
    // 蜂鸣器短促提示音
    BUZZER_ON();
    HAL_Delay(100);
    BUZZER_OFF();
    
    // 串口发送启动信息
    UART_SendString("\r\n");
    UART_SendString("========================================\r\n");
    UART_SendString("    STM32F103 System Starting...\r\n");
    UART_SendString("========================================\r\n");
    
    // ==================== 第二阶段：硬件自检 ====================
    // LED自检 - 依次点亮所有LED
    UART_SendString("Hardware self-test in progress...\r\n");
    
    for (i = 0; i < 4; i++) {
        // 关闭所有LED
        LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_OFF();
        
        // 点亮当前LED
        switch (i) {
            case 0: LED1_ON(); break;
            case 1: LED2_ON(); break;
            case 2: LED3_ON(); break;
            case 3: LED4_ON(); break;
        }
        
        // 数码管显示当前LED编号
        SEG7_DisplayDigitNew(i + 1);
        
        // 串口输出LED测试信息
        sprintf(boot_info, "LED%d test completed\r\n", i + 1);
        UART_SendString(boot_info);
        
        HAL_Delay(300);
    }
    
    // ==================== 第三阶段：数码管测试 ====================
    UART_SendString("7-Segment display test starting...\r\n");
    
    // 数码管循环显示0-9
    for (i = 0; i < 10; i++) {
        SEG7_DisplayDigitNew(i);
        sprintf(boot_info, "Display showing: %d\r\n", i);
        UART_SendString(boot_info);
        HAL_Delay(200);
    }
    
    // ==================== TM1650四位数码管测试 ====================
    UART_SendString("TM1650 4-digit display test starting...\r\n");
    
    // TM1650显示测试数字
    TM1650_WriteNumber(1234);
    sprintf(boot_info, "TM1650 showing: 1234\r\n");
    UART_SendString(boot_info);
    HAL_Delay(1000);
    
    TM1650_WriteNumber(5678);
    sprintf(boot_info, "TM1650 showing: 5678\r\n");
    UART_SendString(boot_info);
    HAL_Delay(1000);
    
    TM1650_WriteString("HELL");
    sprintf(boot_info, "TM1650 showing: HELL\r\n");
    UART_SendString(boot_info);
    HAL_Delay(1000);
    
    // ==================== 第四阶段：蜂鸣器测试 ====================
    UART_SendString("Buzzer test...\r\n");
    
    // 蜂鸣器发出三声提示音
    for (i = 0; i < 3; i++) {
        BUZZER_ON();
        HAL_Delay(150);
        BUZZER_OFF();
        HAL_Delay(150);
    }
    
    // ==================== 第五阶段：系统信息显示 ====================
    UART_SendString("System Information:\r\n");
    UART_SendString("- Processor: STM32F103C8T6\r\n");
    UART_SendString("- Clock: 72MHz\r\n");
    UART_SendString("- UART: USART1 (115200,8,N,1)\r\n");
    UART_SendString("- Peripherals: 4 LEDs, 1 Buzzer, 1 7-Segment Display, 1 TM1650 4-digit Display\r\n");
    
    // ==================== 第六阶段：启动完成提示 ====================
    // LED全部点亮表示启动完成
    LED1_ON(); LED2_ON(); LED3_ON(); LED4_ON();
    
    // 数码管显示"8"表示系统就绪
    SEG7_DisplayDigitNew(8);
    
    // TM1650显示"8888"表示系统就绪
    TM1650_WriteNumber(8888);
    
    // 蜂鸣器长音提示启动完成
    BUZZER_ON();
    HAL_Delay(500);
    BUZZER_OFF();
    
    // 串口发送启动完成信息
    UART_SendString("========================================\r\n");
    UART_SendString("    System Boot Complete!\r\n");
    UART_SendString("    All peripherals initialized successfully\r\n");
    UART_SendString("========================================\r\n");
    UART_SendString("Available Commands:\r\n");
    UART_SendString("  LED_ON    - Turn on LED1\r\n");
    UART_SendString("  LED_OFF   - Turn off LED1\r\n");
    UART_SendString("  BUZZER_ON - Turn on buzzer\r\n");
    UART_SendString("  BUZZER_OFF- Turn off buzzer\r\n");
    UART_SendString("  HELP  - Show help information\r\n");
    UART_SendString("========================================\r\n");
    
    // ==================== 第七阶段：进入正常工作状态 ====================
    // 关闭所有LED，准备进入正常工作模式
    LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_OFF();
    
    // 数码管显示"0"表示系统就绪
    SEG7_DisplayDigitNew(0);
    
    UART_SendString("System ready, waiting for user commands...\r\n\r\n");
}

/**
 * @brief 简化版开机信息显示函数（快速启动）
 * @param None
 * @retval None
 * @note   快速显示开机信息，适用于生产环境
 */
static void System_Boot_Info_Display_Fast(void) {
    // 变量定义 - 放在函数开头以提高编译器兼容性
    char boot_info[64];
    
    // ==================== 快速启动提示 ====================
    // 蜂鸣器短促提示音
    BUZZER_ON();
    HAL_Delay(50);
    BUZZER_OFF();
    
    // 串口发送快速启动信息
    UART_SendString("\r\n");
    UART_SendString("STM32F103 System Boot Complete\r\n");
    
    // ==================== 快速硬件测试 ====================
    // LED快速测试 - 全部点亮后关闭
    LED1_ON(); LED2_ON(); LED3_ON(); LED4_ON();
    HAL_Delay(200);
    LED1_OFF(); LED2_OFF(); LED3_OFF(); LED4_OFF();
    
    // 数码管显示系统就绪
    SEG7_DisplayDigitNew(8);
    HAL_Delay(200);
    SEG7_DisplayDigitNew(0);
    
    // 蜂鸣器确认音
    BUZZER_ON();
    HAL_Delay(100);
    BUZZER_OFF();
    
    // 串口输出就绪信息
    UART_SendString("System ready, type HELP for available commands\r\n\r\n");
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
  // 变量定义 - 放在函数开头以提高编译器兼容性
  uint32_t start_tick;
  uint8_t current_digit=0;
  uint32_t last_switch_time=0;
  uint32_t current_time=0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  
  // ==================== 硬件初始化 ====================
  SEG7_Init();  // 初始化数码管
  TM1650_Init();  // 初始化TM1650四位数码管
  //KEY_Init();  // 初始化按键硬件
  UART_Comm_Init();  // 初始化串口通信
  
  // ==================== 开机信息显示 ====================
  System_Boot_Info_Display();  // 显示开机信息和硬件自检
  
  // ==================== 主循环初始化 ====================
  last_switch_time = HAL_GetTick();  // 记录开始时间
  
  // ==================== 主循环 ====================
  while (1) {
    
    if(KEY_GetState(KEY_MICRO_PIN) != KEY_PRESSED) {
      SEG7_Display_Task();      // 按键未按下时执行数码管循环显示任务
      TM1650_Display_Task();    // 按键未按下时执行TM1650四位数码管显示任务
      led_circle_task();        // 按键未按下时执行LED转圈圈效果任务
			 // ADC测试任务
			ADC_Test_Task();
    }
    else {
      SEG7_DisplayDigitNew(0);  // 按键按下时显示0
      TM1650_WriteNumber(0);    // TM1650显示0
			    //  串口通信演示任务
			UART_Comm_Demo_Task();
    }
    

    
   
    
    // 这里可以添加其他任务，如：
    // - 按键检测任务
    // - 传感器读取任务
    // - LED控制任务
    // - 通信任务等 
  }
  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    led_circle_task(); // 执行LED转圈圈效果任务
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
